home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Development Platforms / CSMP Digests / csmp-v1-018.txt < prev    next >
Encoding:
Text File  |  1992-11-18  |  56.2 KB  |  1,528 lines  |  [TEXT/MPS ]

  1. C.S.M.P. Digest             Sun, 15 Mar 92       Volume 1 : Issue 18
  2.  
  3. Today's Topics:
  4.  
  5.     Determining size of file
  6.     Opening docs in non-app-event-aware apps--SOLUTION
  7.     Fatest code to fill memory?
  8.  
  9.  
  10. The Comp.Sys.Mac.Programmer Digest is moderated by Michael A. Kelly.
  11.  
  12. These digests are available (by using FTP, account anonymous, your email
  13. address as password) in the pub/mac/csmp-digest directory on ftp.cs.uoregon.
  14. edu (try skinner.cs.uoregon.edu if that doesn't work).  This is also the home
  15. of the comp.sys.mac.programmer Frequently Asked Questions list.
  16.  
  17. These digests are also available via email.  Just send a note saying that you
  18. want to be on the digest mailing list to mkelly@cs.uoregon.edu, and you will
  19. automatically receive each new digest as it is created.
  20.  
  21. The articles in these digests are taken directly from comp.sys.mac.programmer.
  22. They are not edited; all articles included in this digest are in their original
  23. posted form.  The only articles that are -not- included in these digests are
  24. those which didn't receive any replies (except those that give information
  25. rather than ask a question).  All replies to each article are concatenated
  26. onto the original article in the order in which they were received.  Article
  27. threads are not added to the digests until the last article added to the
  28. thread is at least one month old (this is to ensure that the thread is dead
  29. before adding it to the digests).
  30.  
  31. Send administrative mail to mkelly@cs.uoregon.edu.
  32.  
  33. -------------------------------------------------------
  34.  
  35. From: crow@ccwf.cc.utexas.edu (David L. Crow)
  36. Subject: Determining size of file
  37. Date: 9 Feb 92 01:51:43 GMT
  38. Organization: The University of Texas at Austin, Austin TX
  39.  
  40.  
  41.     I am trying to write a program that can determine the size of a file.  I
  42.   am using Think C 5.0 with System 7.  In UNIX, I would use the "stat" sub-
  43.   routine, but I am a little unsure how to get this info on the Mac.  I have
  44.   been trying to use FSOpen and PBHGetFInfo, but they aren't working as I
  45.   would suspect from reading Inside Mac.  Are these the right routines to
  46.   use?  Is there a better way?  Maybe using the ANSI library instead of the
  47.   Toolbox?
  48.  
  49.     Thanks!
  50. -- 
  51. David L. Crow    crow@ccwf.cc.utexas.edu
  52.  
  53.  
  54.  
  55. - -------------------------
  56.  
  57. From: mcmath@csb1.nlm.nih.gov (Chuck McMath)
  58. Subject:  Determining size of file
  59. Date: 10 Feb 92 12:53:32 GMT
  60. Organization: MSD
  61.  
  62. In article <66447@ut-emx.uucp>, crow@ccwf.cc.utexas.edu (David L. Crow) writes:
  63. >     I am trying to write a program that can determine the size of a file.  I
  64. >   am using Think C 5.0 with System 7.  In UNIX, I would use the "stat" sub-
  65. >   routine, but I am a little unsure how to get this info on the Mac.  I have
  66. >   been trying to use FSOpen and PBHGetFInfo, but they aren't working as I
  67. >   would suspect from reading Inside Mac.  Are these the right routines to
  68. >   use?  Is there a better way?  Maybe using the ANSI library instead of the
  69. >   Toolbox?
  70. >     Thanks!
  71. > -- 
  72. > David L. Crow    crow@ccwf.cc.utexas.edu
  73.  
  74. Open the file, then call (Pascal syntax):
  75.  
  76.        err := GetEOF(refNum, logEOF);
  77.  
  78. logEOF === 'logical end-of-file' === size of file in bytes.
  79.  
  80. Inside Mac Volume II, pages 93,112.
  81.  
  82. Cheers!
  83.  
  84. chuck
  85.  
  86.                        --chuck mcmath-
  87.                     mcmath@csb1.nlm.nih.gov
  88.   MSD, Inc. * National Library of Medicine * National Institutes of Health
  89.                        Bethesda, MD 20894
  90.  
  91.  
  92.  
  93. - -------------------------
  94.  
  95. From: keith@Apple.COM (Keith Rollin)
  96. Subject:  Determining size of file
  97. Date: 10 Feb 92 21:25:26 GMT
  98. Organization: Apple Computer Inc., Cupertino, CA
  99.  
  100. In article <66447@ut-emx.uucp> crow@ccwf.cc.utexas.edu (David L. Crow) writes:
  101. >
  102. >    I am trying to write a program that can determine the size of a file.  I
  103. >  am using Think C 5.0 with System 7.  In UNIX, I would use the "stat" sub-
  104. >  routine, but I am a little unsure how to get this info on the Mac.  I have
  105. >  been trying to use FSOpen and PBHGetFInfo, but they aren't working as I
  106. >  would suspect from reading Inside Mac.  Are these the right routines to
  107. >  use?  Is there a better way?  Maybe using the ANSI library instead of the
  108. >  Toolbox?
  109. >
  110. Use PBHGetFInfo or PBGetCatInfo. You don't need to futz with FSOpen.
  111.  
  112. Using the built-in File Manager calls is the best way. Using ANSI calls
  113. usually have the problem of having to translate themselves into the
  114. built-in calls. This takes longer, and runs the risk of losing
  115. something in the translation.
  116.  
  117. -- 
  118. - ----------------------------------------------------------------------------
  119. Keith Rollin           ---            <Taligent .signature under construction>
  120. Disclaimer: Pretty soon, I really _won't_ be speaking for Apple...
  121.  
  122.  
  123.  
  124. - -------------------------
  125.  
  126. From: oster@well.sf.ca.us (David Phillip Oster)
  127. Subject:  Determining size of file
  128. Date: 13 Feb 92 13:59:31 GMT
  129. Organization: Whole Earth 'Lectronic Link, Sausalito, CA
  130.  
  131. In article <62649@apple.Apple.COM> keith@Apple.COM (Keith Rollin) writes:
  132. >Use PBHGetFInfo or PBGetCatInfo. You don't need to futz with FSOpen.
  133. Don't you have to check the file system type before you can use these calls?
  134. I believe that "bad things will happen" if you try to use these on a MFS
  135. file system. At least FSOpen() doesn't care whether the input is MFS or HFS.
  136. -- 
  137. -- David Phillip Oster - At least the government doesn't make death worse.
  138. -- oster@well.sf.ca.us = {backbone}!well!oster
  139.  
  140.  
  141.  
  142. - -------------------------
  143.  
  144. From: jcav@quads.uchicago.edu (JohnC)
  145. Subject:  Determining size of file
  146. Date: 14 Feb 92 21:50:36 GMT
  147. Organization: The Royal Society for Putting Things on Top of Other Things
  148.  
  149. In article <29997@well.sf.ca.us> oster@well.sf.ca.us (David Phillip Oster) writes:
  150. >In article <62649@apple.Apple.COM> keith@Apple.COM (Keith Rollin) writes:
  151. >>Use PBHGetFInfo or PBGetCatInfo. You don't need to futz with FSOpen.
  152. >Don't you have to check the file system type before you can use these calls?
  153. >I believe that "bad things will happen" if you try to use these on a MFS
  154. >file system. At least FSOpen() doesn't care whether the input is MFS or HFS.
  155.  
  156. Well, if HFS is running then the worst that can happen is that you'll get a
  157. "wrongVolType" error.  Of course, if HFS is _not_ running then you'll get a
  158. system error when you try to call _PBGetCatInfo.
  159.  
  160. -- 
  161. John Cavallino                  |  EMail: jcav@midway.uchicago.edu
  162. University of Chicago Hospitals |         John_Cavallino@uchfm.bsd.uchicago.edu
  163. Office of Facilities Management | USMail: 5841 S. Maryland Ave, MC 0953
  164. B0 f++ c+ g+ k s+(+) e+ h- pv   |         Chicago, IL  60637
  165.  
  166.  
  167.  
  168. ---------------------------
  169.  
  170. From: greeny@top.cis.syr.edu (Jonathan Greenfield)
  171. Subject: Opening docs in non-app-event-aware apps--SOLUTION
  172. Organization: CIS Dept., Syracuse University
  173. Date: Sat, 8 Feb 92 21:28:01 EST
  174.  
  175. Thanks to the several people who tried to help me with this problem.  It
  176. was actually quite frustrating to have people telling me "just send an 'odoc'
  177. event, and the Process Manager will take care of it" since I had already
  178. tried doing this.
  179.  
  180. I eventually decided to mess around and see if there was some kind of "trick"
  181. that was required.  What I discovered is that (for some reason that is
  182. unknown to me, and apparently undocumented) you have to await a reply when
  183. you send the 'odoc' event, in order for the Process Manager to properly
  184. open the document.
  185.  
  186. Perhaps DTS should put this information in one of their "snippets" or 
  187. something like that.  (Or perhaps they already have, though I'm not aware
  188. of it...)
  189.  
  190. In any case, the application involved, LaunchPad, was just submitted to
  191. the sumex archive, and should be available soon.  It is a very simple 
  192. application that allows Clean-Desktop-types to clear off their desktops,
  193. and still have drag-and-drop access to a lot of different applications.
  194.  
  195. It's freeware, so try it out, and let me know what you think.
  196.  
  197. --
  198. J. S. Greenfield                                         greeny@top.cis.syr.edu
  199. (I like to put 'greeny' here, 
  200. but my d*mn system wants a 
  201. *real* name!)                        "What's the difference between an orange?"
  202.  
  203.  
  204.  
  205. - -------------------------
  206.  
  207. From: grobbins@Apple.COM (Grobbins)
  208. Subject:  Opening docs in non-app-event-aware apps--SOLUTION
  209. Date: 11 Feb 92 09:01:42 GMT
  210. Organization: Apple CTS
  211.  
  212. In article <1992Feb8.212801.7577@newstand.syr.edu> greeny@top.cis.syr.edu (Jonathan Greenfield) writes:
  213. >What I discovered is that (for some reason that is
  214. >unknown to me, and apparently undocumented) you have to await a reply when
  215. >you send the 'odoc' event, in order for the Process Manager to properly
  216. >open the document.
  217.  
  218. What you have to do is call WaitNextEvent, since events don't get sent
  219. until WNE time.  Using kAEWaitReply makes the Apple Event manager call
  220. WaitNextEvent for you, as mentioned on page 6-60 of Inside Mac VI.
  221.  
  222. >Perhaps DTS should put this information in one of their "snippets" or 
  223. >something like that.  (Or perhaps they already have, though I'm not aware
  224. >of it...)
  225.  
  226. The latest information from DTS is in the Tech Notes and the Q&A Stack.
  227.  
  228. Grobbins            grobbins@apple.com
  229.  
  230.  
  231.  
  232. - -------------------------
  233.  
  234. From: greeny@top.cis.syr.edu (Jonathan Greenfield)
  235. Subject:  Opening docs in non-app-event-aware apps--SOLUTION
  236. Date: 13 Feb 92 18:05:13 GMT
  237. Organization: CIS Dept., Syracuse University
  238.  
  239. In article <62679@apple.Apple.COM> grobbins@Apple.COM (Grobbins) writes:
  240. >In article <1992Feb8.212801.7577@newstand.syr.edu> greeny@top.cis.syr.edu (Jonathan Greenfield) writes:
  241. >>What I discovered is that (for some reason that is
  242. >>unknown to me, and apparently undocumented) you have to await a reply when
  243. >>you send the 'odoc' event, in order for the Process Manager to properly
  244. >>open the document.
  245. >
  246. >What you have to do is call WaitNextEvent, since events don't get sent
  247. >until WNE time.  Using kAEWaitReply makes the Apple Event manager call
  248. >WaitNextEvent for you, as mentioned on page 6-60 of Inside Mac VI.
  249.  
  250. This is not a sufficient explanation, since the Apple event is properly
  251. posted, without any trouble, as long as the 'odoc' does not have to
  252. be converted to "puppet strings."
  253.  
  254. Since the AE posting behavior differs depending upon whether or not
  255. conversion to "puppet strings" is necessary, I can only conclude that the
  256. need to wait is due to the Process Manager's need to make the conversion,
  257. and not due to the Event Manager's method for posting the event.
  258.  
  259. --
  260. J. S. Greenfield                                         greeny@top.cis.syr.edu
  261. (I like to put 'greeny' here, 
  262. but my d*mn system wants a 
  263. *real* name!)                        "What's the difference between an orange?"
  264.  
  265.  
  266.  
  267. ---------------------------
  268.  
  269. From: taihou@iss.nus.sg (Tng Tai Hou)
  270. Subject: Fatest code to fill memory?
  271. Organization: Institute of Systems Science, NUS, Singapore
  272. Date: Mon, 10 Feb 1992 15:43:46 GMT
  273.  
  274. Can anyone recommend sample 'c' or 680x0 assembly code to fill 
  275. contiguous memory with some value? For example:
  276.  
  277. int i;
  278. Ptr p;
  279.  
  280. p = baseAddr;
  281. for (i=0; i<100; i++
  282.   *p++ = color;
  283.  
  284. Is this the best code? I use ThinkC 5.0.
  285.  
  286. Would appreciate all kinds of answer on this newsgroup.
  287. My little code segment is for a FTQD (Faster Than QuickDraw) 8-bit line
  288. drawing routine, and also a convex polygon fill routine.
  289.  
  290. Thanks in advance.
  291.  
  292. Tai Hou
  293. Singapore
  294.  
  295.  
  296.  
  297.  
  298. - -------------------------
  299.  
  300. From: CXT105@psuvm.psu.edu (Christopher Tate)
  301. Subject:  Fatest code to fill memory?
  302. Date: 10 Feb 92 21:32:15 GMT
  303. Organization: Penn State University
  304.  
  305. In article <1992Feb10.154346.23488@nuscc.nus.sg>, taihou@iss.nus.sg (Tng Tai
  306. Hou) says:
  307. >
  308. >Can anyone recommend sample 'c' or 680x0 assembly code to fill
  309. >contiguous memory with some value? For example:
  310. >
  311. >int i;
  312. >Ptr p;
  313. >
  314. >p = baseAddr;
  315. >for (i=0; i<100; i++)
  316. >  *p++ = color;
  317.  
  318. Going with straight assembly is your best option for a highly-optimized
  319. application like fast graphics.  Try something like:
  320.  
  321. asm {
  322.      movea  baseAddr, a0    /* equivalent to Ptr p above */
  323.      move   100, d0         /* loop counter */
  324.      move.l  0x1C1C1C1C,d1  /* assuming 8-bit pixels set to hex 1C */
  325. @1:  move.l  d1,(a0)+       /* write 4 pixels */
  326.      dbeq    d0, @1         /* decrement d0, branch to @1 if non-zero */
  327. }
  328.  
  329. This code is really icky, but the important part is that it writes 4
  330. pixels per access (assuming 8-bit pixels), and uses the DBEQ instruction
  331. for speed.  Caches will love that tight loop.
  332.  
  333. Caveats are that it also assumes that you're moving a multiple of 4
  334. pixels -- if you aren't, then you'll have to adjust the limits of the
  335. loop accordingly, and special-case the last three or fewer pixels.
  336. Also, it assumes that the base address is word aligned.  If it isn't
  337. (e.g. there's an extra pixel at the beginning of a scan line), you'll
  338. have to special case that, too.
  339.  
  340. Setting D1 to be the proper value without being able to assume that the
  341. value is a constant is a little more complex, but not really hard.  It's
  342. left as an exercise to the reader.  :-)
  343.  
  344. - -----
  345. Christopher Tate                 |  Cryptogram #7:
  346. cxt105@psuvm.psu.edu             |
  347. CXT105@PSUVM.BITNET              |  Z XZG AYRPOVR LVTLPYTW
  348. - -------------------------------|  YL IYQW TYDPR.
  349. Send me the answer; I love mail! |
  350.  
  351.  
  352.  
  353. - -------------------------
  354.  
  355. From: jesjones@milton.u.washington.edu (Jesse Jones)
  356. Subject:  Fatest code to fill memory?
  357. Organization: University of Washington, Seattle
  358. Date: Tue, 11 Feb 1992 00:36:54 GMT
  359.  
  360.  
  361.    Chris Tate is right: assembly code is definitely the best way to go
  362. if you want your graphic routines to run as fast as possible. The code
  363. he has is fine as long as you remember that the decrement and branch
  364. instructions are restricted to word length counter registers.
  365.  
  366.    I wrote an assembly routine a while back that fills an arbitrary
  367. amount of memory with words. If you're stuffing longwords you can
  368. speed this up some. The routine is in Modula-2 and in the form of
  369. an inline procedure. The machine language was generated using a DA
  370. called Quik Hex (which I highly recommend).
  371.  
  372. PROCEDURE FillMem (adr, bytes: ADDRESS; filler: WORD);
  373.    INLINE2(321FH),      (* MOVE.W    (A7)+, D1  *)
  374.    INLINE2(241FH),      (* MOVE.L    (A7)+, D2  *)
  375.    INLINE2(201FH),      (* MOVE.L    (A7)+, D0  *)
  376.    INLINE2(0A055H),     (* StripAddress        *)
  377.    INLINE2(2040H),      (* MOVE.L    D0, A0     *)
  378.    INLINE2(30C1H),      (* MOVE.W    D1, (A0)+  *)
  379.    INLINE2(5582H),      (* SUBQ.L    #2, D2     *)
  380.    INLINE2(6EFAH);      (* BGT.S    -4         *)
  381.  
  382.  
  383.   --Jesse
  384.  
  385.  
  386.  
  387.  
  388. - -------------------------
  389.  
  390. From: neeri@iis.ethz.ch (Matthias Ulrich Neeracher)
  391. Subject:  Fatest code to fill memory?
  392. Date: 11 Feb 92 16:43:44 GMT
  393. Organization: Integrated Systems Laboratory, ETH, Zurich
  394.  
  395. In article <92041.163215CXT105@psuvm.psu.edu> Christopher Tate <CXT105@psuvm.psu.edu> writes:
  396. >In article <1992Feb10.154346.23488@nuscc.nus.sg>, taihou@iss.nus.sg (Tng Tai
  397. >Hou) says:
  398. >>
  399. >>Can anyone recommend sample 'c' or 680x0 assembly code to fill
  400. >>contiguous memory with some value? For example:
  401. >>
  402. >>int i;
  403. >>Ptr p;
  404. >>
  405. >>p = baseAddr;
  406. >>for (i=0; i<100; i++)
  407. >>  *p++ = color;
  408. >
  409. >Going with straight assembly is your best option for a highly-optimized
  410. >application like fast graphics.  Try something like:
  411. >
  412. >asm {
  413. >     movea  baseAddr, a0    /* equivalent to Ptr p above */
  414. >     move   100, d0         /* loop counter */
  415. >     move.l  0x1C1C1C1C,d1  /* assuming 8-bit pixels set to hex 1C */
  416. >@1:  move.l  d1,(a0)+       /* write 4 pixels */
  417. >     dbeq    d0, @1         /* decrement d0, branch to @1 if non-zero */
  418. >}
  419. >
  420. >This code is really icky, but the important part is that it writes 4
  421. >pixels per access (assuming 8-bit pixels), and uses the DBEQ instruction
  422. >for speed.  Caches will love that tight loop.
  423.  
  424. But you probably can do better than that by unrolling the inner loop by a
  425. factor of 8, resulting in:
  426.  
  427. @1    MOVE.L    D1, (A0)+
  428.     MOVE.L  D1, (A0)+
  429.     MOVE.L  D1, (A0)+
  430.     MOVE.L  D1, (A0)+
  431.     MOVE.L  D1, (A0)+
  432.     MOVE.L  D1, (A0)+
  433.     MOVE.L  D1, (A0)+
  434.     MOVE.L  D1, (A0)+
  435.     DBEQ    D0, @1
  436.  
  437. >Caveats are that it also assumes that you're moving a multiple of 4
  438. >pixels -- if you aren't, then you'll have to adjust the limits of the
  439. >loop accordingly, and special-case the last three or fewer pixels.
  440. >Also, it assumes that the base address is word aligned.  If it isn't
  441. >(e.g. there's an extra pixel at the beginning of a scan line), you'll
  442. >have to special case that, too.
  443.  
  444. My above code is even more tricky in this respect, and you have to ask yourself
  445. whether the work is justifed.
  446.  
  447. For an interesting study in loop unrolling, take a look at Apple's
  448. implementation of _BlockMove.
  449.  
  450. Matthias
  451.  
  452. - ---
  453. Matthias Neeracher                                      neeri@iis.ethz.ch
  454.  `We say "gestalt" when things combine to act in ways we can't explain'
  455.                              -- Marvin Minsky, _The Society Of Mind_
  456.  
  457.  
  458.  
  459. - -------------------------
  460.  
  461. From: Michael_Hecht@mac.sas.com (Michael Hecht)
  462. Subject:  Fatest code to fill memory?
  463. Date: 11 Feb 92 16:32:15 GMT
  464. Organization: SAS Institute Inc.
  465.  
  466. In article <NEERI.92Feb11104344@iis.ethz.ch>,
  467.    neeri@iis.ethz.ch (Matthias Ulrich Neeracher) writes:
  468. > In article <92041.163215CXT105@psuvm.psu.edu>
  469. >    Christopher Tate <CXT105@psuvm.psu.edu> writes:
  470. > >
  471. > >In article <1992Feb10.154346.23488@nuscc.nus.sg>,
  472. > >   taihou@iss.nus.sg (Tng Tai Hou) says:
  473. > >>
  474. > >>Can anyone recommend sample 'c' or 680x0 assembly code to fill
  475. > >>contiguous memory with some value? For example:
  476. > >>
  477. > >>[simple byte fill loop example deleted]
  478. > >
  479. > >Going with straight assembly is your best option for a highly-optimized
  480. > >application like fast graphics.  Try something like:
  481. > >
  482. > >[longword assembler loop example deleted]
  483. > >
  484. > >[...] it writes 4
  485. > >pixels per access (assuming 8-bit pixels), and uses the DBEQ instruction
  486. > >for speed.  Caches will love that tight loop.
  487. > But you probably can do better than that by unrolling the inner loop by a
  488. > factor of 8, resulting in:
  489. >[unrolled assembler loop example deleted]
  490. > >Caveats are that it also assumes that you're moving a multiple of 4
  491. > >pixels. [...] Also, it assumes that the base address is word aligned. [...]
  492. > My above code is even more tricky in this respect, and you have to ask yourself
  493. > whether the work is justifed.
  494.  
  495.  
  496. Here's some code I wrote a while back. It "unrolls" the loop by using the
  497. movem instruction to fill memory in 28-byte chunks. This code works in
  498. THINK C 4; I haven't yet checked that it also works with THINK C 5. However,
  499. the THINK C 5 manual states that register assignment is disabled for any
  500. function containing asm statements.
  501.  
  502. Note that all the caveats mentioned above are handled here.
  503.  
  504. --Michael
  505.  
  506. =======================================================================
  507. Michael P. Hecht                 | Internet:  Michael_Hecht@mac.sas.com
  508. SAS Institute Inc.; Cary, NC USA | AppleLink: SAS.HECHT
  509. =======================================================================
  510.  
  511. /* Number of registers we can use */
  512. #define NREGS        7
  513. /* Number of bytes we can fill in one chunk */
  514. #define AMOUNT        NREGS*sizeof(long)
  515.  
  516. /* Fill memory starting at p for len bytes with c */
  517. void FillMem( char *p, short len, char c )
  518. {
  519.     /* Use one address register for q */
  520.     register char *    q;
  521.  
  522.     /* Use five data registers... */
  523.     register long    r1, r2, r3, r4, r5;
  524.     /* ...and remaining two address registers for filling */
  525.     register char    *r6, *r7;
  526.  
  527.  
  528.     /* Sanity check for len */
  529.     if( len <= 0 )
  530.         return;
  531.  
  532.     /* Replicate character to all four bytes of r1 */
  533.     r1 = c & 0xFF;
  534.     r1 |= r1 << 8;
  535.     r1 |= r1 << 16;
  536.  
  537.     /* Fill all registers with fill character */
  538.     r2 = r3 = r4 = r5 = r1;
  539.     r6 = r7 = ( char * )r1;
  540.  
  541.     /* Align p on a long-word address */
  542.     while(( long )p & 0x00000003 ) {
  543.         *p++ = r1;
  544.         if( !( --len ))
  545.             break;
  546.     }
  547.  
  548.     /*
  549.      *    Fill as many full chunks as possible.
  550.      *
  551.      *    We have to use the predecrement mode, because the
  552.      *    680x0 doesn't allow movem'ing registers to memory
  553.      *    in postincrement mode (that's only allowed in the
  554.      *    opposite direction).
  555.      */
  556.     q = p + AMOUNT;
  557.     p += len;
  558.     for( ; q < p; q += 2*AMOUNT )
  559.         asm {
  560.             movem.l        r1/r2/r3/r4/r5/r6/r7,-(q)
  561.         }
  562.  
  563.     /* Fill any leftover partial chunk, a byte at a time */
  564.     q -= AMOUNT;
  565.     for( ; q < p; )
  566.         asm {
  567.             move.b        r1,(q)+
  568.         }
  569. }
  570.  
  571.  
  572.  
  573. - -------------------------
  574.  
  575. From: suitti@ima.isc.com (Stephen Uitti)
  576. Subject:  Fatest code to fill memory?
  577. Organization: Interactive Systems, Cambridge, MA 02138-5302
  578. Date: Tue, 11 Feb 1992 18:06:44 GMT
  579.  
  580. In article <92041.163215CXT105@psuvm.psu.edu> Christopher Tate <CXT105@psuvm.psu.edu> writes:
  581. >In article <1992Feb10.154346.23488@nuscc.nus.sg>, taihou@iss.nus.sg (Tng Tai
  582. >Hou) says:
  583. >>Can anyone recommend sample 'c' or 680x0 assembly code to fill
  584. >>contiguous memory with some value? For example:
  585. >>
  586. >>int i;
  587. >>Ptr p;
  588. >>
  589. >>p = baseAddr;
  590. >>for (i=0; i<100; i++)
  591. >>  *p++ = color;
  592. >
  593. >Going with straight assembly is your best option for a highly-optimized
  594. >application like fast graphics.  Try something like:
  595. >
  596. >asm {
  597. >     movea  baseAddr, a0    /* equivalent to Ptr p above */
  598. >     move   100, d0         /* loop counter */
  599. >     move.l  0x1C1C1C1C,d1  /* assuming 8-bit pixels set to hex 1C */
  600. >@1:  move.l  d1,(a0)+       /* write 4 pixels */
  601. >     dbeq    d0, @1         /* decrement d0, branch to @1 if non-zero */
  602. >}
  603.  
  604. Note: dbeq checks the condition codes first.  You need to jump
  605. over the move at @1: for the first loop.  Also, the code is not
  606. good for clearing to zeros, since the condition code will be set
  607. to exit the loop on the first pass.  See code for "amemset", below.
  608. When it all comes down, I couldn't get dbeq to work right.
  609.  
  610. I did this in Think C 5.02, on a Mac IIci with cache board.  In
  611. the options:  Code Optimization I had "Honor 'register' first"
  612. were set.  Note:  all of these routines expect "count" to mean
  613. "this many long words", not "this many bytes".
  614.  
  615. /* This is the code that I'd use first */
  616. /* Assume long aligned "buf" */
  617. void cmemset(register long *buf, register long value,
  618.     register unsigned long count)
  619. {
  620.     do {
  621.         *buf++ = value;
  622.     } while (--count);
  623. }
  624.  
  625. /* This compiles to the same as the above code */
  626. void bmemset(register long *buf, register long value,
  627.     register unsigned long count)
  628. {
  629.     asm {
  630.     @1:    move.l    value,(buf)+    /* do { *buf++ = value; */
  631.         subq.l    #1, count    /* } while (--count); */
  632.         bne.s    @1
  633.     }
  634. }
  635.  
  636. /* This is how to use "dbeq" correctly.
  637.  * Note that it will exit early (after the first move.l
  638.  * if "value" is zero.  This is, of course, wrong.
  639.  */
  640. void amemset(register long *buf, register long value,
  641.     register unsigned long count)
  642. {
  643.     asm {
  644.         bra.s    @2        /* dbeq checks first */
  645.     @1:    move.l    value,(buf)+    /* do { *buf++ = value; */
  646.     @2:    dbeq    count, @1    /* } while (--count); */
  647.     }
  648. }
  649.  
  650. Note that the thinkC "memset" ANSI routine uses one move.b per
  651. loop.  It uses "asm", but it would have been the same code in C.
  652.  
  653. For my money, I'd let the C compiler do the linkage work when doing
  654. assembly.  Let it figure out where to put variables.  Let it
  655. do the C calling sequence.  Just check the work it did with
  656. the Disassemble command.
  657.  
  658. Finally, let's examine Duff's device for loop unrolling.
  659.  
  660. void dmemset(register long *buf, register long value,
  661.     register unsigned long count)
  662. {
  663.     register unsigned long loop;
  664.  
  665.     loop = (count + 8 - 1) >> 3;
  666.     switch (count & (8 - 1)) {
  667.     case 0:
  668.         do {
  669.             *buf++ = value;
  670.     case 7:
  671.             *buf++ = value;
  672.     case 6:
  673.             *buf++ = value;
  674.     case 5:
  675.             *buf++ = value;
  676.     case 4:
  677.             *buf++ = value;
  678.     case 3:
  679.             *buf++ = value;
  680.     case 2:
  681.             *buf++ = value;
  682.     case 1:
  683.             *buf++ = value;
  684.         } while (--loop);
  685.     }
  686. }
  687.  
  688. This compiles a nicely unrolled loop that will handle any number
  689. of longwords.  The switch gets you into the loop at the right
  690. spot for the first loop, and then the loop fills 8 longwords at a
  691. time until it is done.  The loop overhead is 1/8th as much.
  692. Duff's device looks gross, but remember that a switch is really
  693. just a computed "goto", and the "case"'s are just labels.  I
  694. believe this hack is blessed by ANSI C.
  695.  
  696. Think C uses "subq.l"/"bne.s", rather than "dbeq", so if you
  697. wanted that too, you'd have to code it in assembly.  Though
  698. "Disassemble" can help here, it is further complicated by the
  699. fact that "dbeq" checks the condition codes first.  "dbeq" is an
  700. instruction that "check condition codes for zero, if nonzero
  701. subtract one, if not -1 then branch".  The instruction I really
  702. wanted was the PDP-11 "sob" - "subtract one and branch if not
  703. zero".  In fact, given that "dbeq" is so complicated, I wouldn't
  704. be surprised if "subq.l"/"bne.s" weren't faster, or at least
  705. nearly the same speed as "dbeq".  I'd say, off hand, that "dbeq"
  706. is useless.
  707.  
  708. A short benchmark of the above routines called with
  709. a buffer 100,000 4 byte words long, a value of 0x40404040, and
  710. a count of 100,000, and each routine is called 1,000 times,
  711. the times on a Mac IIci with cache card were:
  712.  
  713. Routine  Time in seconds
  714. amemset  22 (dbeq) - however, it didn't seem to work right.
  715. bmemset  78 (subq.l/bne.s but in asm)
  716. cmemset  78 (subq.l/bne.s but in C)
  717. dmemset  78 (unrolled 8 times with subq.l/bne.s at bottom)
  718.  
  719. dmemset not was faster than bmemset or cmemset.  It was not the
  720. speedup I'd have expected.  Loop unrolling does not appear to
  721. benefit this code.
  722.  
  723. On a new topic:
  724.  
  725. One thing I'd wish for in Think C is that "Disassemble" was
  726. completely compatible with "asm".  For example, "Disassemble"
  727. produces code such as
  728.  
  729.     move.l    #$01020304,D0
  730.  
  731. whereas "asm" wants to see
  732.  
  733.     move.l    #01020304,d0
  734.  
  735. This is just a pain.
  736.  
  737. Stephen.
  738. suitti@ima.isc.com
  739.  
  740.  
  741.  
  742. - -------------------------
  743.  
  744. From: d88-jwa@hemul.nada.kth.se (Jon W{tte)
  745. Subject:  Fatest code to fill memory?
  746. Date: 11 Feb 92 17:28:42 GMT
  747. Organization: Royal Institute of Technology, Stockholm, Sweden
  748.  
  749. .ch> neeri@iis.ethz.ch (Matthias Ulrich Neeracher) writes:
  750.  
  751.    >>Can anyone recommend sample 'c' or 680x0 assembly code to fill
  752.    >>contiguous memory with some value? For example:
  753.  
  754.    >>p = baseAddr;
  755.    >>for (i=0; i<100; i++)
  756.    >>  *p++ = color;
  757.  
  758.    >@1:  move.l  d1,(a0)+       /* write 4 pixels */
  759.    >     dbeq    d0, @1         /* decrement d0, branch to @1 if non-zero */
  760.  
  761.    @1    MOVE.L    D1, (A0)+
  762.        MOVE.L  D1, (A0)+
  763.        MOVE.L  D1, (A0)+
  764.        MOVE.L  D1, (A0)+
  765.        MOVE.L  D1, (A0)+
  766.        MOVE.L  D1, (A0)+
  767.        MOVE.L  D1, (A0)+
  768.        MOVE.L  D1, (A0)+
  769.        DBEQ    D0, @1
  770.  
  771. What's wrong with MOVEM.L ? That should copy 60 bytes per instruction
  772. fetch...
  773.  
  774.    For an interesting study in loop unrolling, take a look at Apple's
  775.    implementation of _BlockMove.
  776.  
  777. True. Especially on 040 ROMs where they move a cache line each time :-)
  778. (Couldn't youjust get the address of BlockMove and call that directly ?
  779. That might be fast enough !)
  780.  
  781.  
  782. --
  783. This Signature is distributed under the conditions of the Signature License,
  784. available at a fee from   h+@nada.kth.se  (Jon W{tte)  Reading the Signature
  785. implies that you accept to be bound by the terms in said License. Should you
  786. not agree on any of these terms, you must return the Signature unread to me.
  787.  
  788.  
  789.  
  790. - -------------------------
  791.  
  792. From: orpheus@reed.edu (P. Hawthorne)
  793. Subject:  Fatest code to fill memory?
  794. Date: 12 Feb 92 05:53:24 GMT
  795. Organization: Reed College, Portland OR
  796.  
  797.  
  798.     I spent too long trying to best BlockMove. I tried just about
  799. everything I could think of. BlockMove is weak from tight inner loops and
  800. short moves. For pure flat out speed on short moves from an inner loop,
  801. one can do better.
  802.  
  803.     If you never have overlapping source and destination blocks, it can
  804. be made even faster. Perhaps not surprisingly, it is faster in general to
  805. use a predecrement mode move if possible. Since the only thing that makes
  806. BlockMove weak is that it eats cache, one's own routines should not.
  807. MOVEM is great for the 68000, but the overhead of saving and restoring
  808. registers outweighs the reduced cache damage for tight loops, where we
  809. have a chance of improving on BlockMove. I was aiming at best performance
  810. on 68020/68030 machines, but I suspect that the MOVEM routine included
  811. would compare decently with BlockMove on 68040 machines.
  812.  
  813.     Here're some of the most successful of the routines I was pitting
  814. against BlockMove. Judge me not by their elegance or lack thereof. These
  815. reflect the experimentation process I was undergoing, and not everything
  816. I learned. I very much look forward to any commentary, however, first
  817. machine code project and all... Good, bad, attrocious?
  818.  
  819.     I'll defer the explanation of them until someone specifically asks,
  820. since I expect folks who are interested to be able to read this with
  821. little or no effort. Formal source will be included with the Panacea
  822. Class Library, which I shall be releasing Real Soon Now.
  823.  
  824.     Incidentally, the fellow who loaned me the m68k series manuals was
  825. utterly nonplussed at the idea of a fast memory copy. He thought it was
  826. too simple, and offered me a tight printf and a multiprocessor FFT.
  827.  
  828.     The general purpose mover I ultimately wrote will first decide if
  829. content overlaps and go to postincrement or predecrement cases
  830. appropriately. Those check to see if the number of characters is small,
  831. medium or large. If large, 4096 chars, then it calls BlockMove. It does
  832. not jump straight to the address of BlockMove, which it ought, I know.
  833.  
  834.     I include the Pascal INLINE for that in the next article. I'm afraid I
  835. lost my ResEdit copy. Oh, one more thing. Please pardon the syntax, these
  836. are hand assembled from machine code within ResEdit's hex editor. (Just
  837. don't happen to own MPW Asm)
  838.  
  839.     Theus (orpheus@reed.edu)
  840.  
  841. Machine code source starts here. Pascal INLINEs in next article:
  842.  
  843. memcpy 1 byte 0 alignment (note: byte count means bytes before looping)
  844. +0000  000000  MOVE.L     (A7)+,D0            | 201F
  845. +0002  000002  MOVEA.L    (A7)+,A1            | 225F
  846. +0004  000004  MOVEA.L    (A7)+,A0            | 205F
  847. +0006  000006  SUBQ.L     #$1,D0              | 5380
  848. +0008  000008  BMI.S      memcpy+$0018        | 6B0E
  849. +000A  00000A  MOVE.B     (A0)+,(A1)+         | 12D8
  850. +000C  00000C  DBF        D0,memcpy+$000A     | 51C8 FFFC
  851. +0010  000010  SUBI.L     #$00010000,D0       | 0480 0001 0000
  852. +0016  000016  BGT.S      memcpy+$000A        | 6EF2
  853.  
  854. memcpy 2 byte 0 alignment
  855. +0000  000000  MOVE.L     (A7)+,D0            | 201F
  856. +0002  000002  MOVEA.L    (A7)+,A1            | 225F
  857. +0004  000004  MOVEA.L    (A7)+,A0            | 205F
  858. +0006  000006  LSR.L      #$1,D0              | E288
  859. +0008  000008  BCC.S      memcpy+$000E        | 6404
  860. +000A  00000A  MOVE.B     (A0)+,(A1)+         | 12D8
  861. +000C  00000C  TST.L      D0                  | 4A80
  862. +000E  00000E  BEQ.S      memcpy+$0020        | 6710
  863. +0010  000010  SUBQ.L     #$1,D0              | 5380
  864. +0012  000012  MOVE.W     (A0)+,(A1)+         | 32D8
  865. +0014  000014  DBF        D0,memcpy+$0012     | 51C8 FFFC
  866. +0018  000018  SUBI.L     #$00010000,D0       | 0480 0001 0000
  867. +001E  00001E  BGT.S      memcpy+$0012        | 6EF2
  868.  
  869. memcpy 8 byte 0 alignment
  870. +0000  000000  MOVE.L     (A7)+,D0            | 201F
  871. +0002  000002  MOVEA.L    (A7)+,A1            | 225F
  872. +0004  000004  MOVEA.L    (A7)+,A0            | 205F
  873. +0006  000006  LSR.L      #$1,D0              | E288
  874. +0008  000008  BCC.S      memcpy+$000E        | 6404
  875. +000A  00000A  MOVE.B     (A0)+,(A1)+         | 12D8
  876. +000C  00000C  TST.L      D0                  | 4A80
  877. +000E  00000E  BEQ.S      memcpy+$0036        | 6726
  878. +0010  000010  LSR.L      #$1,D0              | E288
  879. +0012  000012  BCC.S      memcpy+$001A        | 6406
  880. +0014  000014  MOVE.W     (A0)+,(A1)+         | 32D8
  881. +0016  000016  TST.L      D0                  | 4A80
  882. +0018  000018  BEQ.S      memcpy+$0036        | 671C
  883. +001A  00001A  LSR.L      #$1,D0              | E288
  884. +001C  00001C  BCC.S      memcpy+$0024        | 6406
  885. +001E  00001E  MOVE.L     (A0)+,(A1)+         | 22D8
  886. +0020  000020  TST.L      D0                  | 4A80
  887. +0022  000022  BEQ.S      memcpy+$0036        | 6712
  888. +0024  000024  SUBQ.L     #$1,D0              | 5380
  889. +0026  000026  MOVE.L     (A0)+,(A1)+         | 22D8
  890. +0028  000028  MOVE.L     (A0)+,(A1)+         | 22D8
  891. +002A  00002A  DBF        D0,memcpy+$0026     | 51C8 FFFA
  892. +002E  00002E  SUBI.L     #$00010000,D0       | 0480 0001 0000
  893. +0034  000034  BGT.S      memcpy+$0026        | 6EF0
  894.  
  895. memcpy 32 byte 0 alignment
  896. +0000  000000  MOVE.L     (A7)+,D0            | 201F
  897. +0002  000002  MOVEA.L    (A7)+,A1            | 225F
  898. +0004  000004  MOVEA.L    (A7)+,A0            | 205F
  899. +0006  000006  LSR.L      #$1,D0              | E288
  900. +0008  000008  BCC.S      memcpy+$000E        | 6404
  901. +000A  00000A  MOVE.B     (A0)+,(A1)+         | 12D8
  902. +000C  00000C  TST.L      D0                  | 4A80
  903. +000E  00000E  BEQ.S      memcpy+$005E        | 674E
  904. +0010  000010  LSR.L      #$1,D0              | E288
  905. +0012  000012  BCC.S      memcpy+$001A        | 6406
  906. +0014  000014  MOVE.W     (A0)+,(A1)+         | 32D8
  907. +0016  000016  TST.L      D0                  | 4A80
  908. +0018  000018  BEQ.S      memcpy+$005E        | 6744
  909. +001A  00001A  LSR.L      #$1,D0              | E288
  910. +001C  00001C  BCC.S      memcpy+$0024        | 6406
  911. +001E  00001E  MOVE.L     (A0)+,(A1)+         | 22D8
  912. +0020  000020  TST.L      D0                  | 4A80
  913. +0022  000022  BEQ.S      memcpy+$005E        | 673A
  914. +0024  000024  LSR.L      #$1,D0              | E288
  915. +0026  000026  BCC.S      memcpy+$0030        | 6408
  916. +0028  000028  MOVE.L     (A0)+,(A1)+         | 22D8
  917. +002A  00002A  MOVE.L     (A0)+,(A1)+         | 22D8
  918. +002C  00002C  TST.L      D0                  | 4A80
  919. +002E  00002E  BEQ.S      memcpy+$005E        | 672E
  920. +0030  000030  LSR.L      #$1,D0              | E288
  921. +0032  000032  BCC.S      memcpy+$0040        | 640C
  922. +0034  000034  MOVE.L     (A0)+,(A1)+         | 22D8
  923. +0036  000036  MOVE.L     (A0)+,(A1)+         | 22D8
  924. +0038  000038  MOVE.L     (A0)+,(A1)+         | 22D8
  925. +003A  00003A  MOVE.L     (A0)+,(A1)+         | 22D8
  926. +003C  00003C  TST.L      D0                  | 4A80
  927. +003E  00003E  BEQ.S      memcpy+$005E        | 671E
  928. +0040  000040  SUBQ.L     #$1,D0              | 5380
  929. +0042  000042  MOVE.L     (A0)+,(A1)+         | 22D8
  930. +0044  000044  MOVE.L     (A0)+,(A1)+         | 22D8
  931. +0046  000046  MOVE.L     (A0)+,(A1)+         | 22D8
  932. +0048  000048  MOVE.L     (A0)+,(A1)+         | 22D8
  933. +004A  00004A  MOVE.L     (A0)+,(A1)+         | 22D8
  934. +004C  00004C  MOVE.L     (A0)+,(A1)+         | 22D8
  935. +004E  00004E  MOVE.L     (A0)+,(A1)+         | 22D8
  936. +0050  000050  MOVE.L     (A0)+,(A1)+         | 22D8
  937. +0052  000052  DBF        D0,memcpy+$0042     | 51C8 FFEE
  938. +0056  000056  SUBI.L     #$00010000,D0       | 0480 0001 0000
  939. +005C  00005C  BGT.S      memcpy+$0042        | 6EE4
  940.  
  941. memcpy 256 byte 0 alignment
  942. +0000  000000  MOVE.L     (A7)+,D0            | 201F
  943. +0002  000002  MOVEA.L    (A7)+,A1            | 225F
  944. +0004  000004  MOVEA.L    (A7)+,A0            | 205F
  945. +0006  000006  LSR.L      #$1,D0              | E288
  946. +0008  000008  BCC.S      memcpy+$000E        | 6404
  947. +000A  00000A  MOVE.B     (A0)+,(A1)+         | 12D8
  948. +000C  00000C  TST.L      D0                  | 4A80
  949. +000E  00000E  BEQ        memcpy+$0118        | 6700 0108
  950. +0012  000012  LSR.L      #$1,D0              | E288
  951. +0014  000014  BCC.S      memcpy+$001E        | 6408
  952. +0016  000016  MOVE.W     (A0)+,(A1)+         | 32D8
  953. +0018  000018  TST.L      D0                  | 4A80
  954. +001A  00001A  BEQ        memcpy+$0118        | 6700 00FC
  955. +001E  00001E  LSR.L      #$1,D0              | E288
  956. +0020  000020  BCC.S      memcpy+$002A        | 6408
  957. +0022  000022  MOVE.L     (A0)+,(A1)+         | 22D8
  958. +0024  000024  TST.L      D0                  | 4A80
  959. +0026  000026  BEQ        memcpy+$0118        | 6700 00F0
  960. +002A  00002A  LSR.L      #$1,D0              | E288
  961. +002C  00002C  BCC.S      memcpy+$0038        | 640A
  962. +002E  00002E  MOVE.L     (A0)+,(A1)+         | 22D8
  963. +0030  000030  MOVE.L     (A0)+,(A1)+         | 22D8
  964. +0032  000032  TST.L      D0                  | 4A80
  965. +0034  000034  BEQ        memcpy+$0118        | 6700 00E2
  966. +0038  000038  LSR.L      #$1,D0              | E288
  967. +003A  00003A  BCC.S      memcpy+$004A        | 640E
  968. +003C  00003C  MOVE.L     (A0)+,(A1)+         | 22D8
  969. +003E  00003E  MOVE.L     (A0)+,(A1)+         | 22D8
  970. +0040  000040  MOVE.L     (A0)+,(A1)+         | 22D8
  971. +0042  000042  MOVE.L     (A0)+,(A1)+         | 22D8
  972. +0044  000044  TST.L      D0                  | 4A80
  973. +0046  000046  BEQ        memcpy+$0118        | 6700 00D0
  974. +004A  00004A  LSR.L      #$1,D0              | E288
  975. +004C  00004C  BCC.S      memcpy+$0064        | 6416
  976. +004E  00004E  MOVE.L     (A0)+,(A1)+         | 22D8
  977. +0050  000050  MOVE.L     (A0)+,(A1)+         | 22D8
  978. +0052  000052  MOVE.L     (A0)+,(A1)+         | 22D8
  979. +0054  000054  MOVE.L     (A0)+,(A1)+         | 22D8
  980. +0056  000056  MOVE.L     (A0)+,(A1)+         | 22D8
  981. +0058  000058  MOVE.L     (A0)+,(A1)+         | 22D8
  982. +005A  00005A  MOVE.L     (A0)+,(A1)+         | 22D8
  983. +005C  00005C  MOVE.L     (A0)+,(A1)+         | 22D8
  984. +005E  00005E  TST.L      D0                  | 4A80
  985. +0060  000060  BEQ        memcpy+$0118        | 6700 00B6
  986. +0064  000064  LSR.L      #$1,D0              | E288
  987. +0066  000066  BCC.S      memcpy+$008E        | 6426
  988. +0068  000068  MOVE.L     (A0)+,(A1)+         | 22D8
  989. +006A  00006A  MOVE.L     (A0)+,(A1)+         | 22D8
  990. +006C  00006C  MOVE.L     (A0)+,(A1)+         | 22D8
  991. +006E  00006E  MOVE.L     (A0)+,(A1)+         | 22D8
  992. +0070  000070  MOVE.L     (A0)+,(A1)+         | 22D8
  993. +0072  000072  MOVE.L     (A0)+,(A1)+         | 22D8
  994. +0074  000074  MOVE.L     (A0)+,(A1)+         | 22D8
  995. +0076  000076  MOVE.L     (A0)+,(A1)+         | 22D8
  996. +0078  000078  MOVE.L     (A0)+,(A1)+         | 22D8
  997. +007A  00007A  MOVE.L     (A0)+,(A1)+         | 22D8
  998. +007C  00007C  MOVE.L     (A0)+,(A1)+         | 22D8
  999. +007E  00007E  MOVE.L     (A0)+,(A1)+         | 22D8
  1000. +0080  000080  MOVE.L     (A0)+,(A1)+         | 22D8
  1001. +0082  000082  MOVE.L     (A0)+,(A1)+         | 22D8
  1002. +0084  000084  MOVE.L     (A0)+,(A1)+         | 22D8
  1003. +0086  000086  MOVE.L     (A0)+,(A1)+         | 22D8
  1004. +0088  000088  TST.L      D0                  | 4A80
  1005. +008A  00008A  BEQ        memcpy+$0118        | 6700 008C
  1006. +008E  00008E  MOVEM.L    D1-D7/A2-A6,-(A7)   | 48E7 7F3E
  1007. +0092  000092  LSR.L      #$1,D0              | E288
  1008. +0094  000094  BCC.S      memcpy+$00BE        | 6428
  1009. +0096  000096  MOVEM.L    (A0)+,D1-D7/A2-A6   | 4CD8 7CFE
  1010. +009A  00009A  MOVEM.L    D1-D7/A2-A6,(A1)    | 48D1 7CFE
  1011. +009E  00009E  ADDA.W     #$0030,A1           | D2FC 0030
  1012. +00A2  0000A2  MOVEM.L    (A0)+,D1-D7/A2-A6   | 4CD8 7CFE
  1013. +00A6  0000A6  MOVEM.L    D1-D7/A2-A6,(A1)    | 48D1 7CFE
  1014. +00AA  0000AA  ADDA.W     #$0030,A1           | D2FC 0030
  1015. +00AE  0000AE  MOVEM.L    (A0)+,D2-D7/A4/A5   | 4CD8 30FC
  1016. +00B2  0000B2  MOVEM.L    D2-D7/A4/A5,(A1)    | 48D1 30FC
  1017. +00B6  0000B6  ADDA.W     #$0020,A1           | D2FC 0020
  1018. +00BA  0000BA  TST.L      D0                  | 4A80
  1019. +00BC  0000BC  BEQ.S      memcpy+$0114        | 6756
  1020. +00BE  0000BE  SUBQ.L     #$1,D0              | 5380
  1021. +00C0  0000C0  MOVEM.L    (A0)+,D1-D7/A2-A6   | 4CD8 7CFE
  1022. +00C4  0000C4  MOVEM.L    D1-D7/A2-A6,(A1)    | 48D1 7CFE
  1023. +00C8  0000C8  ADDA.W     #$0030,A1           | D2FC 0030
  1024. +00CC  0000CC  MOVEM.L    (A0)+,D1-D7/A2-A6   | 4CD8 7CFE
  1025. +00D0  0000D0  MOVEM.L    D1-D7/A2-A6,(A1)    | 48D1 7CFE
  1026. +00D4  0000D4  ADDA.W     #$0030,A1           | D2FC 0030
  1027. +00D8  0000D8  MOVEM.L    (A0)+,D1-D7/A2-A6   | 4CD8 7CFE
  1028. +00DC  0000DC  MOVEM.L    D1-D7/A2-A6,(A1)    | 48D1 7CFE
  1029. +00E0  0000E0  ADDA.W     #$0030,A1           | D2FC 0030
  1030. +00E4  0000E4  MOVEM.L    (A0)+,D1-D7/A2-A6   | 4CD8 7CFE
  1031. +00E8  0000E8  MOVEM.L    D1-D7/A2-A6,(A1)    | 48D1 7CFE
  1032. +00EC  0000EC  ADDA.W     #$0030,A1           | D2FC 0030
  1033. +00F0  0000F0  MOVEM.L    (A0)+,D1-D7/A2-A6   | 4CD8 7CFE
  1034. +00F4  0000F4  MOVEM.L    D1-D7/A2-A6,(A1)    | 48D1 7CFE
  1035. +00F8  0000F8  ADDA.W     #$0030,A1           | D2FC 0030
  1036. +00FC  0000FC  MOVEM.L    (A0)+,D1-D4         | 4CD8 001E
  1037. +0100  000100  MOVEM.L    D1-D4,(A1)          | 48D1 001E
  1038. +0104  000104  ADDA.W     #$0010,A1           | D2FC 0010
  1039. +0108  000108  DBF        D0,memcpy+$00C0     | 51C8 FFB6
  1040. +010C  00010C  SUBI.L     #$00010000,D0       | 0480 0001 0000
  1041. +0112  000112  BGT.S      memcpy+$00C0        | 6EAC
  1042. +0114  000114  MOVEM.L    (A7)+,D1-D7/A2-A6   | 4CDF 7CFE
  1043.  
  1044. End of machine code source. Pascal INLINEs in next article.
  1045.  
  1046.  
  1047.  
  1048. - -------------------------
  1049.  
  1050. From: orpheus@reed.edu (P. Hawthorne)
  1051. Subject:  Fatest code to fill memory?
  1052. Date: 12 Feb 92 06:20:48 GMT
  1053. Organization: Reed College, Portland OR
  1054.  
  1055. Pascal INLINE source starts here.
  1056.  
  1057. procedure CopyBlockInline;
  1058. inline {This is the most general mover included. Does overlaps.}
  1059. $226E, $000C, $206E, $0010, $202E, $0008, $2208, $D280, $B289, $5DC1, {}
  1060. $B3C8, $5DC2, $8202, $6700, $00D6, $0C80, $0000, $00C4, $6E3A, $E288, {}
  1061. $6404, $12D8, $4A80, $6700, $019A, $E288, $6408, $32D8, $4A80, $6700, {}
  1062. $018E, $E288, $6408, $22D8, $4A80, $6700, $0182, $5380, $22D8, $22D8, {}
  1063. $51C8, $FFFA, $0480, $0001, $0000, $6EF0, $6000, $016C, $0C80, $0000, {}
  1064. $0D00, $6E00, $0084, $E288, $6406, $12D8, $4A80, $677A, $E288, $6406, {}
  1065. $32D8, $4A80, $6770, $E288, $6406, $22D8, $4A80, $6766, $E288, $6408, {}
  1066. $22D8, $22D8, $4A80, $675A, $E288, $640C, $22D8, $22D8, $22D8, $22D8, {}
  1067. $4A80, $674A, $E288, $6414, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, {}
  1068. $22D8, $22D8, $4A80, $6732, $5380, $22D8, $22D8, $22D8, $22D8, $22D8, {}
  1069. $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, {}
  1070. $22D8, $51C8, $FFDE, $0480, $0001, $0000, $6ED4, $6002, $A02E, $6000, {}
  1071. $00DA, $0C80, $0000, $00C4, $6E3E, $D1C0, $D3C0, $E288, $6404, $1320, {}
  1072. $4A80, $6700, $00C2, $E288, $6408, $3320, $4A80, $6700, $00B6, $E288, {}
  1073. $6408, $2320, $4A80, $6700, $00AA, $5380, $2320, $2320, $51C8, $FFFA, {}
  1074. $0480, $0001, $0000, $6EF0, $6000, $0094, $0C80, $0000, $0D00, $6E00, {}
  1075. $0088, $D1C0, $D3C0, $E288, $6406, $1320, $4A80, $677A, $E288, $6406, {}
  1076. $3320, $4A80, $6770, $E288, $6406, $2320, $4A80, $6766, $E288, $6408, {}
  1077. $2320, $2320, $4A80, $675A, $E288, $640C, $2320, $2320, $2320, $2320, {}
  1078. $4A80, $674A, $E288, $6414, $2320, $2320, $2320, $2320, $2320, $2320, {}
  1079. $2320, $2320, $4A80, $6732, $5380, $2320, $2320, $2320, $2320, $2320, {}
  1080. $2320, $2320, $2320, $2320, $2320, $2320, $2320, $2320, $2320, $2320, {}
  1081. $2320, $51C8, $FFDE, $0480, $0001, $0000, $6ED4, $6002, $A02E; {}
  1082.  
  1083. procedure CopyBlock (src, dst: univ Ptr; count: Longint);
  1084. begin {Glue routine that assumes Think Pascal. Watch your registers.}
  1085. CopyBlockInline;
  1086. end;
  1087.  
  1088. procedure CopyMem (src, dst: univ Ptr; count: Longint);
  1089. inline
  1090. $201F, $225F, $205F, $0C80, $0000, $00C4, $6E3A, $E288, $6404, $12D8, {}
  1091. $4A80, $6700, $00BE, $E288, $6408, $32D8, $4A80, $6700, $00B2, $E288, {}
  1092. $6408, $22D8, $4A80, $6700, $00A6, $5380, $22D8, $22D8, $51C8, $FFFA, {}
  1093. $0480, $0001, $0000, $6EF0, $6000, $0090, $0C80, $0000, $0D00, $6E00, {}
  1094. $0084, $E288, $6404, $12D8, $4A80, $677A, $E288, $6406, $32D8, $4A80, {}
  1095. $6770, $E288, $6406, $22D8, $4A80, $6766, $E288, $6408, $22D8, $22D8, {}
  1096. $4A80, $675A, $E288, $640C, $22D8, $22D8, $22D8, $22D8, $4A80, $674A, {}
  1097. $E288, $6414, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, {}
  1098. $4A80, $6732, $5380, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, {}
  1099. $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $51C8, {}
  1100. $FFDE, $0480, $0001, $0000, $6ED4, $6002, $A02E; {}
  1101.  
  1102. procedure CopyMemBackwards (src, dst: univ Ptr; count: Longint);
  1103. inline {Moves memory using predecrement mode}
  1104. $201F, $225F, $205F, $0C80, $0000, $00C4, $6E3E, $D1C0, $D3C0, $E288, {}
  1105. $6404, $1320, $4A80, $6700, $00C2, $E288, $6408, $3320, $4A80, $6700, {}
  1106. $00B6, $E288, $6408, $2320, $4A80, $6700, $00AA, $5380, $2320, $2320, {}
  1107. $51C8, $FFFA, $0480, $0001, $0000, $6EF0, $6000, $0094, $0C80, $0000, {}
  1108. $0D00, $6E00, $0088, $D1C0, $D3C0, $E288, $6404, $1320, $4A80, $677A, {}
  1109. $E288, $6406, $3320, $4A80, $6770, $E288, $6406, $2320, $4A80, $6766, {}
  1110. $E288, $6408, $2320, $2320, $4A80, $675A, $E288, $640C, $2320, $2320, {}
  1111. $2320, $2320, $4A80, $674A, $E288, $6414, $2320, $2320, $2320, $2320, {}
  1112. $2320, $2320, $2320, $2320, $4A80, $6732, $5380, $2320, $2320, $2320, {}
  1113. $2320, $2320, $2320, $2320, $2320, $2320, $2320, $2320, $2320, $2320, {}
  1114. $2320, $2320, $2320, $51C8, $FFDE, $0480, $0001, $0000, $6ED4, $6002, {}
  1115. $A02E; {}
  1116.  
  1117. procedure Copy1 (src, dst: univ Ptr; count: Longint);
  1118. inline
  1119. $201F, $225F, $205F, $E288, $6404, $12D8, $4A80, $6710, $5380, $32D8, {}
  1120. $51C8, $FFFC, $0480, $0001, $0000, $6EF2; {}
  1121.  
  1122. procedure Copy2 (src, dst: univ Ptr; count: Longint);
  1123. inline
  1124. $201F, $225F, $205F, $E288, $6406, $12D8, $4A80, $671A, $E288, $6404, {}
  1125. $32D8, $4A80, $6710, $5380, $22D8, $51C8, $FFFC, $0480, $0001, $0000, {}
  1126. $6EF2; {}
  1127.  
  1128. procedure Copy8 (src, dst: univ Ptr; count: Longint);
  1129. inline
  1130. $201F, $225F, $205F, $E288, $6404, $12D8, $4A80, $6736, $E288, $6406, {}
  1131. $32D8, $4A80, $672C, $E288, $6406, $22D8, $4A80, $6722, $E288, $6408, {}
  1132. $22D8, $22D8, $4A80, $6716, $5380, $22D8, $22D8, $22D8, $22D8, $51C8, {}
  1133. $FFF6, $0480, $0001, $0000, $6EEC; {}
  1134.  
  1135. procedure Copy32 (src, dst: univ Ptr; count: Longint);
  1136. inline
  1137. $201F, $225F, $205F, $E288, $6404, $12D8, $4A80, $6776, $E288, $6406, {}
  1138. $32D8, $4A80, $676C, $E288, $6406, $22D8, $4A80, $6762, $E288, $6408, {}
  1139. $22D8, $22D8, $4A80, $6756, $E288, $640C, $22D8, $22D8, $22D8, $22D8, {}
  1140. $4A80, $6746, $E288, $6414, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, {}
  1141. $22D8, $22D8, $4A80, $672E, $5380, $22D8, $22D8, $22D8, $22D8, $22D8, {}
  1142. $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, {}
  1143. $22D8, $51C8, $FFDE, $0480, $0001, $0000, $6ED4; {}
  1144.  
  1145. procedure Copy64 (src, dst: univ Ptr; count: Longint);
  1146. inline
  1147. $201F, $225F, $205F, $E288, $6404, $12D8, $4A80, $6700, $00B2, $E288, {}
  1148. $6408, $32D8, $4A80, $6700, $00A6, $E288, $6408, $22D8, $4A80, $6700, {}
  1149. $009A, $E288, $640A, $22D8, $22D8, $4A80, $6700, $008C, $E288, $640C, {}
  1150. $22D8, $22D8, $22D8, $22D8, $4A80, $677A, $E288, $6414, $22D8, $22D8, {}
  1151. $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $4A80, $6762, $E288, $6424, {}
  1152. $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, {}
  1153. $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $4A80, $673A, $48E7, $7F3E, {}
  1154. $5380, $4CD8, $7CFE, $48D1, $7CFE, $D2FC, $0030, $4CD8, $7CFE, $48D1, {}
  1155. $7CFE, $D2FC, $0030, $4CD8, $30FC, $48D1, $30FC, $D2FC, $0020, $51C8, {}
  1156. $FFDA, $0480, $0001, $0000, $6ED0, $4CDF, $7CFE; {}
  1157.  
  1158. procedure Copy128 (src, dst: univ Ptr; count: Longint);
  1159. inline
  1160. $201F, $225F, $205F, $E288, $6404, $12D8, $4A80, $6700, $0108, $E288, {}
  1161. $6408, $32D8, $4A80, $6700, $00FC, $E288, $6408, $22D8, $4A80, $6700, {}
  1162. $00F0, $E288, $640A, $22D8, $22D8, $4A80, $6700, $00E2, $E288, $640E, {}
  1163. $22D8, $22D8, $22D8, $22D8, $4A80, $6700, $00D0, $E288, $6416, $22D8, {}
  1164. $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $4A80, $6700, $00B6, {}
  1165. $E288, $6426, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, {}
  1166. $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $4A80, $6700, {}
  1167. $008C, $48E7, $7F3E, $E288, $6428, $4CD8, $7CFE, $48D1, $7CFE, $D2FC, {}
  1168. $0030, $4CD8, $7CFE, $48D1, $7CFE, $D2FC, $0030, $4CD8, $30FC, $48D1, {}
  1169. $30FC, $D2FC, $0020, $4A80, $6756, $5380, $4CD8, $7CFE, $48D1, $7CFE, {}
  1170. $D2FC, $0030, $4CD8, $7CFE, $48D1, $7CFE, $D2FC, $0030, $4CD8, $7CFE, {}
  1171. $48D1, $7CFE, $D2FC, $0030, $4CD8, $7CFE, $48D1, $7CFE, $D2FC, $0030, {}
  1172. $4CD8, $7CFE, $48D1, $7CFE, $D2FC, $0030, $4CD8, $001E, $48D1, $001E, {}
  1173. $D2FC, $0010, $51C8, $FFB6, $0480, $0001, $0000, $6EAC, $4CDF, $7CFE; {}
  1174.  
  1175. procedure Copy128CacheFriendly (src, dst: univ Ptr; count: Longint);
  1176. inline
  1177. $201F, $225F, $205F, $E288, $6404, $12D8, $4A80, $6700, $00AA, $E288, {}
  1178. $6408, $32D8, $4A80, $6700, $009E, $E288, $6408, $22D8, $4A80, $6700, {}
  1179. $0092, $E288, $640A, $22D8, $22D8, $4A80, $6700, $0084, $E288, $640C, {}
  1180. $22D8, $22D8, $22D8, $22D8, $4A80, $6772, $E288, $6414, $22D8, $22D8, {}
  1181. $22D8, $22D8, $22D8, $22D8, $22D8, $22D8, $4A80, $675A, $48E7, $7F3E, {}
  1182. $E288, $641C, $4CD8, $0CFC, $48D1, $0CFC, $D2FC, $0020, $4CD8, $0CFC, {}
  1183. $48D1, $0CFC, $D2FC, $0020, $4A80, $6732, $5380, $4CD8, $7CFE, $48D1, {}
  1184. $7CFE, $D2FC, $0030, $4CD8, $7CFE, $48D1, $7CFE, $D2FC, $0030, $4CD8, {}
  1185. $30FC, $48D1, $30FC, $D2FC, $0020, $51C8, $FFDA, $0480, $0001, $0000, {}
  1186. $6ED0, $4CDF, $7CFE; {}
  1187.  
  1188. End of Pascal INLINE source.
  1189.  
  1190.  
  1191.  
  1192. - -------------------------
  1193.  
  1194. From: lim@iris.ucdavis.edu (Lloyd Lim)
  1195. Subject: BlockMove (was Re: Fatest code to fill memory?)
  1196. Date: 12 Feb 92 10:23:01 GMT
  1197. Organization: U.C. Davis - Department of Electrical Engineering and Computer Science
  1198.  
  1199. In article <D88-JWA.92Feb11182842@hemul.nada.kth.se> d88-jwa@hemul.nada.kth.se (Jon W{tte) writes:
  1200. >.ch> neeri@iis.ethz.ch (Matthias Ulrich Neeracher) writes:
  1201. >
  1202. >   For an interesting study in loop unrolling, take a look at Apple's
  1203. >   implementation of _BlockMove.
  1204. >
  1205. >True. Especially on 040 ROMs where they move a cache line each time :-)
  1206. >(Couldn't youjust get the address of BlockMove and call that directly ?
  1207. >That might be fast enough !)
  1208.  
  1209. The original post was about filling instead of moving but since we're
  1210. off the subject...  :-)
  1211.  
  1212. TN 261 says that BlockMove invalidates the cache for sizes larger than
  1213. 12 bytes because you could be moving code.  I haven't seen anyone
  1214. mention this here.  Does it only invalidate addresses in the destination
  1215. or does it invalidate the whole thing?
  1216.  
  1217. I'd think that if it trashes the whole thing and you're just moving data
  1218. (which is probably 99.99% of the time, or 100% if you are well-behaved),
  1219. it'd be faster to call your own routine to move it.  Even simple routines
  1220. would probably beat a complete loss of the cache.
  1221.  
  1222. +++
  1223. Lloyd Lim     Internet: lim@iris.cs.ucdavis.edu
  1224.               America Online: LimUnltd
  1225.               Compuserve: 72647,660
  1226.               US Mail: 224 Lysle Leach Hall, U.C. Davis, Davis, CA 95616
  1227.  
  1228.  
  1229.  
  1230. - -------------------------
  1231.  
  1232. From: ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
  1233. Subject:  Fastest code to fill memory?
  1234. Date: 12 Feb 92 10:30:23 +1300
  1235. Organization: University of Waikato, Hamilton, New Zealand
  1236.  
  1237. (Reading comments from people about the awkwardness of using DBEQ in a fast
  1238. loop...)
  1239.  
  1240. Pardon me if I'm pointing out something obvious, but you people *do* realize
  1241. there's a version of the DBcc instruction family that _doesn't_ test the
  1242. condition codes, don't you?
  1243.  
  1244. Lawrence D'Oliveiro                       fone: +64-7-856-2889
  1245. Computer Services Dept                     fax: +64-7-838-4066
  1246. University of Waikato            electric mail: ldo@waikato.ac.nz
  1247. Hamilton, New Zealand    37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00
  1248.  
  1249.  
  1250.  
  1251. - -------------------------
  1252.  
  1253. From: taihou@iss.nus.sg (Tng Tai Hou)
  1254. Subject: Fast memory fill results!
  1255. Organization: Institute of Systems Science, NUS, Singapore
  1256. Date: Wed, 12 Feb 1992 11:12:00 GMT
  1257.  
  1258. I asked for help recently on the subject. I received more than 20 replies.
  1259. Thanks to you folks, I have written two versions of what I think is
  1260. the fastest MemSet yet!!! Or at least, the fatest with my current
  1261. knowledge. I believe I have not taken full advantage of the cache in
  1262. the 68020, 030 and 040, or faster opcodes. Maybe someone can enlighten me.
  1263.  
  1264. /*
  1265.    This is the version is 'C'. It first computes the remainder of count%4.
  1266.    If zer0, performs longword memory fills. Else, it computes
  1267.    the nearest longword boundary, fills that, and then fills the remainder
  1268.    (1, 2, or 3) in bytes. Note that value is a longword, and each of its
  1269.    4 bytes contain the value (in my case an 8-bit color value)
  1270. */
  1271. void
  1272. MyAMemSet (register unsigned long *buf, register long value, register
  1273. unsigned long count)
  1274. {
  1275.     register long rem = count%4; /* rem = count & 0x00000003 */
  1276.     register int i;
  1277.     register unsigned char *p, val;
  1278.     
  1279.     if (rem == 0)
  1280.     {
  1281.         for (i=0; i<count; i+=4)
  1282.             *buf++ = value;
  1283.     }
  1284.     else {
  1285.         count &= 0xFFFFFFFC;        /* count = count/4*4 */
  1286.         for (i=0; i<count; i+=4)
  1287.             *buf++ = value;
  1288.         val = value & 0x000000FF;
  1289.         p = (unsigned char*)buf;
  1290.         for (i=0; i<rem; i++)
  1291.             *p++ = val;
  1292.     }
  1293. }
  1294.  
  1295.  
  1296. /*
  1297.     This is a completely handcrafted version.
  1298. */
  1299. void
  1300. MyAMemSet (/*register unsigned long *buf, register long value, register
  1301. unsigned long count*/)
  1302. {
  1303.     asm {
  1304.             move.l    4(sp), d0
  1305.             movea.l    d0, a0            /* a0 = buf */
  1306.             move.l    8(sp), d1        /* d1 = value */
  1307.             move.l    12(sp), d2        /* d2 = count */
  1308.  
  1309.             move.l    d2, d3        /* d3 = rem */
  1310.             and.l    #0x00000003, d3
  1311.             bne.s    @else
  1312.             
  1313.         @5: move.l    d1, (a0)+    /* do *buf++ = value */
  1314.             subq.l    #4, d2
  1315.             bne.s    @5
  1316.             bra        @2
  1317.             
  1318.     @else:    and.l    #0xfffffffc, d2
  1319.         @1:    move.l    d1, (a0)+    /* do (*buf++ = value */
  1320.             subq.l    #4, d2
  1321.             bne.s    @1
  1322.             
  1323.         @3: move.b    d1, (a0)+
  1324.             subq.l    #1, d3
  1325.             bne.s    @3
  1326.             
  1327.         @2:
  1328.     }
  1329. }
  1330.  
  1331.  
  1332. I appreciate all comments and criticisms. Please post to the newsgroup
  1333. for everyone's benefit. Thanks.
  1334.  
  1335. Tai Hou
  1336. Singapore
  1337.  
  1338.  
  1339.  
  1340. - -------------------------
  1341.  
  1342. From: ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
  1343. Subject:  Fast memory fill results!
  1344. Date: 13 Feb 92 10:14:49 +1300
  1345. Organization: University of Waikato, Hamilton, New Zealand
  1346.  
  1347. In article <1992Feb12.111200.25672@nuscc.nus.sg>, taihou@iss.nus.sg
  1348. (Tng Tai Hou) offers a handcrafted memset routine, which I think can
  1349. be speeded up a little more.
  1350.  
  1351. > /*
  1352. >     This is a completely handcrafted version.
  1353. > */
  1354. > void
  1355. > MyAMemSet (/*register unsigned long *buf, register long value, register
  1356. > unsigned long count*/)
  1357. > {
  1358. >     asm {
  1359. >             move.l    4(sp), d0
  1360. >             movea.l    d0, a0            /* a0 = buf */
  1361. >             move.l    8(sp), d1        /* d1 = value */
  1362. >             move.l    12(sp), d2        /* d2 = count */
  1363. >
  1364. >             move.l    d2, d3        /* d3 = rem */
  1365. >             and.l    #0x00000003, d3
  1366. >             bne.s    @else
  1367. >
  1368. >         @5: move.l    d1, (a0)+    /* do *buf++ = value */
  1369. >             subq.l    #4, d2
  1370. >             bne.s    @5
  1371. >             bra        @2
  1372.  
  1373. how about this for a replacement of the sequence from @5:
  1374.  
  1375.             bra.s    @59
  1376.         @51:    swap    d2
  1377.         @52:    move.l    d1, (a0)+
  1378.         @59:    dbra    d2, @52
  1379.             swap    d2
  1380.             dbra    d2, @51
  1381.             bra    @2
  1382. >
  1383. >     @else:    and.l    #0xfffffffc, d2
  1384. >         @1:    move.l    d1, (a0)+    /* do (*buf++ = value */
  1385. >             subq.l    #4, d2
  1386. >             bne.s    @1
  1387.  
  1388. how about:
  1389.  
  1390.         @else:    lsr.l    #2, d2
  1391.             bra.s    @19
  1392.         @11:    swap    d2
  1393.         @12:    move.l    d1, (a0)+
  1394.         @19:    dbra    d2, @12
  1395.             swap    d2
  1396.             dbra    d2, @11
  1397. >
  1398. >         @3: move.b    d1, (a0)+
  1399. >             subq.l    #1, d3
  1400. >             bne.s    @3
  1401.  
  1402. This loop will never iterate more than four times, so it's probably
  1403. not worth speeding up.
  1404.  
  1405. >
  1406. >         @2:
  1407. >     }
  1408. > }
  1409.  
  1410. Lawrence D'Oliveiro
  1411. One-trick asm pony
  1412.  
  1413.  
  1414.  
  1415. - -------------------------
  1416.  
  1417. From: twillis@ec.ecn.purdue.edu (Thomas E Willis)
  1418. Subject:  Fatest code to fill memory?
  1419. Organization: Electrical Engineering, Purdue University
  1420. Date: Thu, 13 Feb 1992 15:00:36 GMT
  1421.  
  1422. In article <1992Feb11.180644.21941@ima.isc.com> suitti@ima.isc.com (Stephen Uitti) writes:
  1423.  
  1424. [tons off stuff deleted]
  1425.  
  1426. >zero".  In fact, given that "dbeq" is so complicated, I wouldn't
  1427. >be surprised if "subq.l"/"bne.s" weren't faster, or at least
  1428. >nearly the same speed as "dbeq".  I'd say, off hand, that "dbeq"
  1429. >is useless.
  1430.  
  1431. if i remember my 68k times right, db<cc> is faster than a subq/bne pair.
  1432. to get around the testing for equal problem, use "dbf" (which always takes
  1433. the branch unless the register decrements to -1).  you do have to "bias"
  1434. your loop counter since you're looping until the index register hits -1.
  1435. for example:
  1436.  
  1437.     moveq    #9,d0        ; causes us to do the move thing 10 times
  1438. @1:    move.l    d1, (a0)+
  1439.     dbf    d0, @1
  1440.  
  1441. this should also work if d1 happens to be 0 (which would cause the dbeq
  1442. code to fall through on the first iteration).
  1443.  
  1444. dbeq is useful in other situations when you want to get out of the loop on
  1445. equal (moving bytes until the first zero?), but it has some "features" that
  1446. make it not quite right for blasting bits around.  kinda the old "right tool
  1447. for the job" type question.
  1448.  
  1449. just my $0.02 worth...
  1450. --
  1451.     - t
  1452. - -------------------------------------------------------------------------
  1453. Tom Willis         / "These are dangerous days, to say what you feel
  1454. Purdue Electrical Engr. / is to dig your own grave." - Sinead O'Connor,
  1455. twillis@ecn.purdue.edu / "Black Boys on Mopeds"
  1456.  
  1457.  
  1458.  
  1459. - -------------------------
  1460.  
  1461. From: ahbritto@iat.com (Arthur H. Britto)
  1462. Subject:  Fatest code to fill memory?
  1463. Date: 13 Feb 92 03:02:57 GMT
  1464. Organization: Information Access Technologies, Inc. of Berkeley, CA
  1465.  
  1466. jesjones@milton.u.washington.edu (Jesse Jones) writes:
  1467.  
  1468. >   Chris Tate is right: assembly code is definitely the best way to go
  1469. >if you want your graphic routines to run as fast as possible. The code
  1470. >he has is fine as long as you remember that the decrement and branch
  1471. >instructions are restricted to word length counter registers.
  1472.  
  1473. Faster than the MOVE.L is the MOVEM instruction.  Save off all the resgisters
  1474. you can and then use the MOVEM instruction.  Of course, you should unwrap
  1475. your loops for maximum effect.  Better yet, have no loops and calculate a
  1476. branch into the code.
  1477.  
  1478. This is how Armor Alley does it.
  1479.  
  1480. Arthur Britto
  1481. -- 
  1482. - ----------------------------------------------------------------------------
  1483. Information Access Technologies, Inc.               Internet: ahbritto@iat.com 
  1484. 46 Shattuck Square, Suite 11             Applelink: ahbritto@iat.com@internet#
  1485. Berkeley, CA 94704-1152                 Voice: 510-704-0160  Fax: 510-704-8019
  1486.  
  1487.  
  1488.  
  1489. - -------------------------
  1490.  
  1491. From: deadman@garnet.berkeley.edu (Ben Haller)
  1492. Subject:  Fatest code to fill memory?
  1493. Date: 15 Feb 92 00:02:58 GMT
  1494. Organization: Stick Software
  1495.  
  1496. In article <1992Feb13.030257.13145@iat.com> ahbritto@iat.com (Arthur H. Britto) writes:
  1497. >Of course, you should unwrap your loops for maximum effect.
  1498.  
  1499.   This is a common fallacy.  In fact, on any Mac upwards of the 68000-based
  1500. ones, unrolling loops kills your performance unless you are very careful.
  1501. You need to make sure that your loop will fit inside the cache size of the
  1502. chip you're running on (different chips have different sizes, too).  In
  1503. general if you're doing memory accesses (filling memory with a value) the
  1504. instructions will pipeline such that the loop branch instruction
  1505. effectively takes a negligable amount of time anyway.  Unrolling may
  1506. speed things up, but beware - if you unroll it too far, you'll start
  1507. thrashing the instruction cache, and your performance will go down the
  1508. tubes.
  1509.  
  1510. -Ben Haller (deadman@garnet.berkeley.edu)
  1511.  
  1512.  
  1513.  
  1514. ---------------------------
  1515.  
  1516. End of C.S.M.P. Digest
  1517. **********************
  1518.